import 'package:flutter/material.dart';
import 'package:flutter_vant/command/overLay.dart' as command;
import 'package:rlstyles/main.dart';

class VanPopupOption {
  // 弹出样式
  final Map<String, dynamic> overlayStyle;
  // 显示关闭图标
  final bool? closeable;
  // 自定义关闭图标
  final IconData? closeIcon;
  // 自定义图标位置
  final String? closeIconPosition;
  // 是否圆角
  final bool? round;
  // 是否显示遮罩层
  final bool overlay;
  // 是否在点击遮罩层后关闭
  final bool closeClickOverlay;
  // 是否开启底部安全区适配
  final bool safeAreaInsetBottom;
  // 显示位置
  final String? position;
  // 子元素
  final Widget? child;
  // 是否显示头部
  final bool isShowHeader;
  // 标题
  final String? title;
  const VanPopupOption({
    this.position,
    this.child,
    this.title = '',
    this.closeIcon,
    this.closeIconPosition = 'top-right',
    this.closeable = false,
    this.isShowHeader = true,
    this.overlay = false,
    this.safeAreaInsetBottom = false,
    this.round = false,
    this.closeClickOverlay = true,
    this.overlayStyle = const {},
  });
}

class VanPopup extends StatefulWidget {
  final VanPopupOption option;
  static List<GlobalKey> _someKey = [];
  VanPopup({Key? key, this.option = const VanPopupOption()}) : super(key: key);
  @override
  _VanPopupState createState() => _VanPopupState();

  static OverlayEntry show(
      {required BuildContext context, VanPopupOption? option}) {
    VanPopup._someKey.add(GlobalKey());
    return command.show(
        context: context,
        key: 'popup',
        child: VanPopup(
            option: option ?? VanPopupOption(), key: VanPopup._someKey.last));
  }

  static remove() {
    _someKey.removeLast();
  }

  static close() {
    if (_someKey.length > 0) {
      (_someKey.last.currentState as _VanPopupState).onCancel();
    }
  }
}

class _VanPopupState extends State<VanPopup> {
  bool isOpen = false;

  @override
  initState() {
    super.initState();
    Future.delayed(Duration(milliseconds: 10)).then((value) => setState(() {
          isOpen = true;
        }));
  }

  getStyle() {
    return {
      'main': {
        CssRule.width: double.infinity,
        CssRule.height: double.infinity,
        CssRule.position: 'relative',
      },
      'center': {
        CssRule.alignItems: 'center',
        CssRule.justifyContent: 'center'
      },
      'header': {
        CssRule.height: 40,
        CssRule.width: double.infinity,
        CssRule.flexDirection: 'row',
        CssRule.alignItems: 'center',
        CssRule.position: 'relative',
        CssRule.borderBottomColor: '#f8f8f8',
        CssRule.borderBottomWidth: 0.4,
        CssRule.borderBottomStyle: 'solid',
      },
      'header-close': {
        CssRule.position: 'abs',
        CssRule.alignItems: 'center',
        CssRule.justifyContent: 'center',
      },
      'close-top-left': {
        CssRule.left: 0.0,
        CssRule.top: 0,
        CssRule.width: 30,
        CssRule.height: 50,
      },
      'close-top-right': {
        CssRule.right: 0.0,
        CssRule.top: 0,
        CssRule.width: 30,
        CssRule.height: 50,
      },
      'close-bottom-left': {
        CssRule.left: 0.0,
        CssRule.bottom: 0,
        CssRule.width: 30,
        CssRule.height: 50,
      },
      'close-bottom-right': {
        CssRule.right: 0.0,
        CssRule.bottom: 0,
        CssRule.width: 30,
        CssRule.height: 50,
      },
      'pop-left': {
        CssRule.position: 'abs',
        CssRule.left: 0,
        CssRule.top: 0,
        CssRule.bottom: 0,
        CssRule.backgroundColor: 'white',
        CssRule.width: 200,
        CssRule.height: double.infinity,
        CssRule.borderRadius: 0,
        CssRule.flexDirection: 'col',
        ...widget.option.overlayStyle
      },
      'pop-right': {
        CssRule.position: 'abs',
        CssRule.right: 0,
        CssRule.top: 0,
        CssRule.bottom: 0,
        CssRule.height: double.infinity,
        CssRule.backgroundColor: 'white',
        CssRule.width: 200,
        CssRule.borderRadius: 0,
        CssRule.flexDirection: 'col',
        ...widget.option.overlayStyle
      },
      'pop-top': {
        CssRule.position: 'abs',
        CssRule.right: 0,
        CssRule.left: 0,
        CssRule.top: 0,
        CssRule.backgroundColor: 'white',
        CssRule.minHeight: 200,
        CssRule.borderRadius: 0,
        CssRule.flexDirection: 'col',
        ...widget.option.overlayStyle
      },
      'pop-bottom': {
        CssRule.flexDirection: 'col',
        CssRule.position: 'abs',
        CssRule.right: 0,
        CssRule.left: 0,
        CssRule.bottom: 0,
        CssRule.backgroundColor: 'white',
        CssRule.borderTopLeftRadius: widget.option.round == true ? 15 : 0,
        CssRule.borderTopRightRadius: widget.option.round == true ? 15 : 0,
        CssRule.minHeight: 200,
        ...widget.option.overlayStyle
      },
      'content': {
        CssRule.width: 80,
        CssRule.height: 80,
        CssRule.alignItems: 'center',
        CssRule.justifyContent: 'center',
        CssRule.backgroundColor: widget.option.child != null ? 'white' : '',
      },
      'body': {
        CssRule.width: '100%',
        CssRule.height: '100%',
        CssRule.alignItems: 'center',
        CssRule.justifyContent: 'center',
        CssRule.backgroundColor: 'rgba(0, 0, 0, 0.3)',
      },
      'shadow': {
        CssRule.position: 'abs',
        CssRule.left: 0,
        CssRule.top: 0,
        CssRule.right: 0,
        CssRule.bottom: 0,
        CssRule.backgroundColor: 'rgba(0, 0, 0, 0.3)',
      }
    };
  }

  renderHeaderClose() {
    if (widget.option.closeable == null || widget.option.closeable == false)
      return SizedBox();
    return Frame(
        styles: {
          ...getStyle()['header-close'] as Map,
          ...getStyle()[
              'close-' + (widget.option.closeIconPosition ?? 'top-right')]
        },
        onClick: onCancel,
        children: [
          Icon(widget.option.closeIcon ?? Icons.close,
              size: 20, color: Colors.black)
        ]);
  }

  getPopStyle() {
    final Map<String, dynamic> styles =
        getStyle()['pop-${widget.option.position}'];
    styles.remove('top');
    styles.remove('left');
    styles.remove('right');
    styles.remove('bottom');
    styles.remove('position');
    return styles;
  }

  renderPop() {
    return Frame(
      styles: getPopStyle(),
      children: [
        renderHeaderClose(),
        widget.option.child ?? Container(),
      ],
    );
  }

  onCancel() {
    if (widget.option.position == null) {
      this.close();
    } else {
      setState(() {
        isOpen = !isOpen;
      });
    }
  }

  getPositionStyle() {
    final Map<String, dynamic> styles =
        getStyle()['pop-${widget.option.position}'];
    final double openHeight = isOpen ? 0.0 : -500;
    return {
      'left': widget.option.position == 'left' ? openHeight : styles['left'],
      'top': widget.option.position == 'top' ? openHeight : styles['top'],
      'right': widget.option.position == 'right' ? openHeight : styles['right'],
      'bottom':
          widget.option.position == 'bottom' ? openHeight : styles['bottom']
    };
  }

  close() {
    Future.delayed(Duration(milliseconds: 100))
        .then((value) => VanPopup.remove());
  }

  onAnimateEnd() {
    if (!isOpen) {
      this.close();
    }
  }

  renderContent() {
    if (widget.option.position == null) {
      return Frame(
        styles: getStyle()['body'],
        children: [
          Frame(
              styles: getStyle()['content'],
              onClick: onCancel,
              children: [widget.option.child ?? SizedBox()])
        ],
      );
    } else {
      return renderAnimated();
    }
  }

  renderAnimated() {
    return AnimatedPositioned(
      left: getSize(size: getPositionStyle()['left'], defValue: null),
      right: getSize(size: getPositionStyle()['right'], defValue: null),
      bottom: getSize(size: getPositionStyle()['bottom'], defValue: null),
      top: getSize(size: getPositionStyle()['top'], defValue: null),
      duration: Duration(milliseconds: 500),
      child: renderPop(),
    );
  }

  renderShadow() {
    return Frame(
      onClick: this.onCancel,
      styles: getStyle()['shadow'],
      children: [],
    );
  }

  @override
  Widget build(BuildContext context) {
    final isCenter = widget.option.position == null;
    return AnimatedOpacity(
        opacity: isOpen ? 1 : 0,
        duration: Duration(milliseconds: 500),
        onEnd: onAnimateEnd,
        child: Frame(styles: {
          ...getStyle()['main'] as Map,
          ...(isCenter ? getStyle()['center'] : {})
        }, children: [
          isCenter != true ? renderShadow() : SizedBox(),
          renderContent(),
        ]));
  }
}
